package ynu.edu.service.impl;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ynu.edu.dto.BusinessFoodDTO;
import ynu.edu.dto.FoodCategoryDTO;
import ynu.edu.dto.FoodDTO;
import ynu.edu.dto.MerchantDTO;
import ynu.edu.entity.Food;
import ynu.edu.entity.FoodCategory;
import ynu.edu.entity.Merchant;
import ynu.edu.repository.FoodCategoryRepository;
import ynu.edu.repository.FoodRepository;
import ynu.edu.repository.MerchantRepository;
import ynu.edu.service.FoodService;

import jakarta.persistence.EntityNotFoundException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 食品服务实现类
 */
@Service
@RequiredArgsConstructor
public class FoodServiceImpl implements FoodService {
    
    private final FoodRepository foodRepository;
    private final MerchantRepository merchantRepository;
    private final FoodCategoryRepository foodCategoryRepository;
    
    /**
     * 根据商家ID获取食品列表
     *
     * @param businessId 商家ID
     * @return 食品列表
     */
    @Override
    public List<FoodDTO> getFoodsByBusinessId(Integer businessId) {
        List<Food> foods = foodRepository.findByBusinessId(businessId);
        
        // 获取所有分类
        List<FoodCategory> categories = foodCategoryRepository.findByBusinessIdOrderBySortAsc(businessId);
        Map<Integer, String> categoryMap = new HashMap<>();
        categories.forEach(category -> categoryMap.put(category.getId(), category.getName()));
        
        return foods.stream()
                .map(food -> {
                    FoodDTO dto = convertToDTO(food);
                    dto.setCategoryName(categoryMap.getOrDefault(food.getCategoryId(), "未分类"));
                    return dto;
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 根据商家ID和分类ID获取食品列表
     *
     * @param businessId 商家ID
     * @param categoryId 分类ID
     * @return 食品列表
     */
    @Override
    public List<FoodDTO> getFoodsByBusinessIdAndCategoryId(Integer businessId, Integer categoryId) {
        List<Food> foods = foodRepository.findByBusinessIdAndCategoryId(businessId, categoryId);
        
        // 获取分类名称
        FoodCategory category = foodCategoryRepository.findById(categoryId)
                .orElse(null);
        String categoryName = category != null ? category.getName() : "未分类";
        
        return foods.stream()
                .map(food -> {
                    FoodDTO dto = convertToDTO(food);
                    dto.setCategoryName(categoryName);
                    return dto;
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 根据ID获取食品
     *
     * @param foodId 食品ID
     * @return 食品信息
     */
    @Override
    public FoodDTO getFoodById(Integer foodId) {
        Food food = foodRepository.findById(foodId)
                .orElseThrow(() -> new EntityNotFoundException("未找到ID为" + foodId + "的食品"));
        
        FoodDTO foodDTO = convertToDTO(food);
        
        // 获取分类名称
        if (food.getCategoryId() != null) {
            FoodCategory category = foodCategoryRepository.findById(food.getCategoryId())
                    .orElse(null);
            if (category != null) {
                foodDTO.setCategoryName(category.getName());
            }
        }
        
        return foodDTO;
    }
    
    /**
     * 根据商家ID获取食品列表和商家信息
     *
     * @param businessId 商家ID
     * @return 商家和食品信息
     */
    @Override
    public BusinessFoodDTO getFoodsWithMerchant(Integer businessId) {
        // 获取商家信息
        Merchant merchant = merchantRepository.findById(businessId)
                .orElseThrow(() -> new EntityNotFoundException("未找到ID为" + businessId + "的商家"));
        
        // 获取分类列表
        List<FoodCategory> categories = foodCategoryRepository.findByBusinessIdOrderBySortAsc(businessId);
        
        // 获取食品列表
        List<Food> foods = foodRepository.findByBusinessId(businessId);
        
        // 转换数据
        MerchantDTO merchantDTO = new MerchantDTO();
        BeanUtils.copyProperties(merchant, merchantDTO);
        
        List<FoodCategoryDTO> categoryDTOs = categories.stream()
                .map(category -> {
                    FoodCategoryDTO dto = new FoodCategoryDTO();
                    BeanUtils.copyProperties(category, dto);
                    return dto;
                })
                .collect(Collectors.toList());
        
        Map<Integer, String> categoryMap = new HashMap<>();
        categories.forEach(category -> categoryMap.put(category.getId(), category.getName()));
        
        List<FoodDTO> foodDTOs = foods.stream()
                .map(food -> {
                    FoodDTO dto = convertToDTO(food);
                    dto.setCategoryName(categoryMap.getOrDefault(food.getCategoryId(), "未分类"));
                    return dto;
                })
                .collect(Collectors.toList());
        
        return new BusinessFoodDTO(merchantDTO, categoryDTOs, foodDTOs);
    }
    
    /**
     * 添加食品
     *
     * @param foodDTO 食品信息
     * @return 添加后的食品信息
     */
    @Override
    @Transactional
    public FoodDTO addFood(FoodDTO foodDTO) {
        // 验证商家是否存在
        if (!merchantRepository.existsById(foodDTO.getBusinessId())) {
            throw new EntityNotFoundException("未找到ID为" + foodDTO.getBusinessId() + "的商家");
        }
        
        // 验证分类是否存在
        if (foodDTO.getCategoryId() != null && !foodCategoryRepository.existsById(foodDTO.getCategoryId())) {
            throw new EntityNotFoundException("未找到ID为" + foodDTO.getCategoryId() + "的食品分类");
        }
        
        Food food = new Food();
        BeanUtils.copyProperties(foodDTO, food);
        food.setCreateTime(LocalDateTime.now());
        food.setUpdateTime(LocalDateTime.now());
        
        Food savedFood = foodRepository.save(food);
        return convertToDTO(savedFood);
    }
    
    /**
     * 更新食品
     *
     * @param foodDTO 食品信息
     * @return 更新后的食品信息
     */
    @Override
    @Transactional
    public FoodDTO updateFood(FoodDTO foodDTO) {
        Food food = foodRepository.findById(foodDTO.getFoodId())
                .orElseThrow(() -> new EntityNotFoundException("未找到ID为" + foodDTO.getFoodId() + "的食品"));
        
        // 验证商家是否存在
        if (!merchantRepository.existsById(foodDTO.getBusinessId())) {
            throw new EntityNotFoundException("未找到ID为" + foodDTO.getBusinessId() + "的商家");
        }
        
        // 验证分类是否存在
        if (foodDTO.getCategoryId() != null && !foodCategoryRepository.existsById(foodDTO.getCategoryId())) {
            throw new EntityNotFoundException("未找到ID为" + foodDTO.getCategoryId() + "的食品分类");
        }
        
        BeanUtils.copyProperties(foodDTO, food);
        food.setUpdateTime(LocalDateTime.now());
        
        Food updatedFood = foodRepository.save(food);
        return convertToDTO(updatedFood);
    }
    
    /**
     * 删除食品
     *
     * @param foodId 食品ID
     */
    @Override
    @Transactional
    public void deleteFood(Integer foodId) {
        if (!foodRepository.existsById(foodId)) {
            throw new EntityNotFoundException("未找到ID为" + foodId + "的食品");
        }
        foodRepository.deleteById(foodId);
    }
    
    /**
     * 搜索食品
     *
     * @param keyword 关键词
     * @return 食品列表
     */
    @Override
    public List<FoodDTO> searchFoods(String keyword) {
        List<Food> foods = foodRepository.findByFoodNameContaining(keyword);
        
        // 获取所有分类
        List<FoodCategory> allCategories = foodCategoryRepository.findAll();
        Map<Integer, String> categoryMap = new HashMap<>();
        allCategories.forEach(category -> categoryMap.put(category.getId(), category.getName()));
        
        return foods.stream()
                .map(food -> {
                    FoodDTO dto = convertToDTO(food);
                    dto.setCategoryName(categoryMap.getOrDefault(food.getCategoryId(), "未分类"));
                    return dto;
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 将实体转换为DTO
     *
     * @param food 食品实体
     * @return 食品DTO
     */
    private FoodDTO convertToDTO(Food food) {
        FoodDTO foodDTO = new FoodDTO();
        BeanUtils.copyProperties(food, foodDTO);
        return foodDTO;
    }
} 